import React, { useState, useEffect } from 'react'
import { compile, run } from '@mdx-js/mdx'
import * as runtime from 'react/jsx-runtime'
import remarkGfm from 'remark-gfm'
import rehypeHighlight from 'rehype-highlight'
import 'highlight.js/styles/github.css'
import './MDXRenderer.css'
import { components } from './components-config'

interface MDXRendererProps {
  mdxContent: string
}

type MDXComponent = React.ComponentType<{
  components?: Record<string, React.ComponentType>
}>

const MDXRenderer: React.FC<MDXRendererProps> = ({ mdxContent }) => {
  const [MDXComponent, setMDXComponent] = useState<MDXComponent | null>(null)

  useEffect(() => {
    const compileMDX = async () => {
      // 编译MDX内容
      // 这段代码是MDX渲染器的核心部分，负责将MDX内容转换为可执行的React组件。
      const compiledMDX = await compile(mdxContent, {
        // outputFormat: 'function-body' ：输出格式为函数体，这样可以直接被 run 函数执行
        // program它生成的是完整的 ES 模块代码（包含 import 语句），而 run() 函数无法直接执行包含 import 语句的代码。
        outputFormat: 'function-body',
        // remarkPlugins: [remarkGfm] ：启用GitHub风格的Markdown扩展（如表格、任务列表等）
        remarkPlugins: [remarkGfm],
        // - rehypePlugins: [rehypeHighlight] ：启用代码高亮功能
        rehypePlugins: [rehypeHighlight],
        // development: false ：生产模式，优化性能
        development: false
      })

      // 运行编译后的代码
      /**
       * run函数作用：
       * - 执行编译后的JavaScript代码，返回一个React组件
       * - String(compiledMDX) ：将编译结果转换为字符串
       * - ...runtime ：提供React运行时环境（包含jsx、jsxs、Fragment等）
       * - baseUrl: import.meta.url ：设置模块的基础URL，用于解析相对路径
       */
      // 返回的{default}，本质是一个react组件
      /**
       *  run 方法是用于处理和执行 MDX 内容的核心函数之一，主要作用是将经过 MDX 编译器处理后的代码（通常是经过 compile 方法转换后的代码）在 JavaScript 环境中运行，并返回执行结果。
       * 返回内容结构：执行后通常会返回一个包含 default 属性的对象，其中 default 是 MDX 内容对应的 React 组件（如果使用 React 环境），此外可能还包含 MDX 中导出的其他变量或组件。
       * 环境依赖：run 方法的执行依赖于具体的 JavaScript 运行环境，并且需要相应的 JSX 运行时（如 React、Preact 等）支持，通常需要在调用时传入这些环境依赖。
       */
      const { default: Component } = await run(String(compiledMDX), {
        ...runtime,
      })

      /**
       * ## 整个流程总结
       * 1. 1. MDX源码 → compile() → JavaScript函数体
       *    - 编译MDX内容，将其转换为可执行的JavaScript函数体
       * 2. 2. JavaScript函数体 → run() → React组件
       *    - 执行编译后的JavaScript代码，返回一个React组件
       * 3. 3. React组件 → 渲染到页面
       *    - 将返回的React组件渲染到页面上
       */

      setMDXComponent(() => Component)
    }

    if (mdxContent) {
      compileMDX()
    }
  }, [mdxContent])

  return (
    <div className='mdx-renderer'>
      {MDXComponent && <MDXComponent components={components} />}
    </div>
  )
}

export default MDXRenderer
